package com.shi.spring_aop.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

@Aspect
@Component
public class testAop {

    //直接在controller层切
    @Before("execution(* com.shi.spring_aop.controller.test.hello(..))")
    public void beforeGetHello(){
        System.out.println("访问了 hello ");

    }
    //创建一个切点
    @Pointcut("execution(* com.shi.spring_aop.service.HelloService.*(..))")
    public void pointcut() {};

    //在切点之后切入
    @After("pointcut()")
    public void afterGetServiceHello(){
        System.out.println("  after  在访问之后切入        访问了 service层 hello");
    }

    //在切点之前切入
    @Before("pointcut()")
    public void beforeGetServiceHello(JoinPoint joinPoint){
        System.out.println("before 在访问之前切入  访问了 service层 hello");
       //通过springmvc来获取请求中的数据
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();//这个RequestContextHolder是Springmvc提供来获得请求的东西
        HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest();
        String url=  request.getRequestURI().toString();
        System.out.println("url  是"+url);

        //JoinPoint对象封装了SpringAop中切面方法的信息,在切面方法中添加JoinPoint参数,就可以获取到封装了该方法信息的JoinPoint对象.
        joinPoint.getSignature();//获取封装了署名信息的对象,在该对象中可以获取到目标方法名,所属类的Class等信息
        Object[] args = joinPoint.getArgs();//获取匹配方法的所有参数\
        joinPoint.getTarget();//获取被代理的对象
        joinPoint.getThis();//获取代理对象


        System.out.println(args.length);
        for(Object arg: args){
            System.out.println(arg);
        }
    }

    //@Around注解可以用来在调用一个具体方法前和调用后来完成一些具体的任务。
    @Around("pointcut()")
    public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {

        //获得方法签名
        joinPoint.getSignature();
        //获取方法参数值数组；
        Object[] args = joinPoint.getArgs();
        //新参数替换就参数
        Object newArg = null;
        for(Object arg:args){
            newArg=arg;
        }
        newArg="我是"+newArg;
        Object[] requeses={newArg};

        //这里的proceed中必须有参数才能成功替换
        joinPoint.proceed(requeses);

        return newArg;
    }

}
